package asteroids;

import be.kuleuven.cs.som.annotate.*;

public class Bullet extends FlyingObject {

	private final Ship source;

	private int bounces;

	/**
	 * Creates a new bullet with the given position, the given velocity, and the
	 * given size.
	 * 
	 * @param position
	 *            The starting position of the bullet to be created
	 * @param velocity
	 *            The starting velocity of the bullet to be created
	 * @param size
	 *            The size of the bullet to be created.
	 * @post the new position of this new bullet is equal to the given initial
	 *       position. |(new this).getPosition() == position
	 * @post the new velocity of this new bullet is equal to the given initial
	 *       velocity. If the given velocity is a null element, we use a new
	 *       velocity that is zero in both directions as the provided velocity.
	 *       |if( velocity != null) (new this).getVelocity() == velocity | else
	 *       (new this).getVelocity() == new Velocity(0,0)
	 * @post the size of this new bullet is equal to the given initial size. |
	 *       (new this).getSize() == size
	 * 
	 * @throws NullPointerException
	 *             This new bullet cannot have the given position as its
	 *             position. |position == null
	 * @throws IllegalArgumentException
	 *             This new bullet cannot have the given size as its size. |
	 *             !isValidSize(size)
	 * @pre		source != null
	 */
	
	public Bullet(Position position, Velocity velocity, double size,
			 Ship source) {
		super(position, velocity, size,  (4.0 / 3.0) * Math.PI
				* Math.pow(size, 3) * 7800000000000D);
		assert source != null;
		this.source = source;
		this.bounces = 0;
		if(source.canHaveAsBullet(this) && !source.hasMaximumBullets())
			source.addFiredBullet(this);

	}

	/**
	 * @post |(new this).getVelocity().getX() == -this.getVelocity().getX()
	 */
	@Override
	public void BounceX() {
		double newX = (-1.0) * (this.getVelocity().getX());
		Velocity newVel = new Velocity(newX, this.getVelocity().getY());
		this.setVelocity(newVel);
		this.bounces++;
	}

	/**
	 * @post |(new this).getVelocity().getY() == -this.getVelocity().getY()
	 */
	@Override
	public void BounceY() {
		double newY = (-1.0) * (this.getVelocity().getY());
		Velocity newVel = new Velocity(this.getVelocity().getX(), newY);
		this.setVelocity(newVel);
		this.bounces++;
	}

	/**
	 * 
	 * @return | result = this.source
	 */
	@Basic
	public Ship getSource() {
		return this.source;
	}

	/**
	 * 
	 * @return | result == this.bounces.
	 */
	public int getBounces() {
		return this.bounces;
	}

	/**
	 * @post |(new this).getBounces == this.getBounces + 1
	 */
	public void incrementBounces() {
		this.bounces++;
	}
	
	/**
	 * 
	 * @param thing
	 *            The entity to be checked for overlap.
	 * @return | result == ( (thing == this)||( getDistanceBetween(this, thing)
	 *         < 0) || !(thing == this.source) )
	 * @throws NullPointerException
	 *             | thing == null
	 */
	@Override
	public boolean overlap(FlyingObject thing) throws NullPointerException {
		if (thing == null) {
			throw new NullPointerException();
		}
		else if (thing == this.source){
			return false;
		}

		else if (thing == this) {
			return true;
		} else {
			return (this.getDistanceBetween(thing) < 0);
		}

	}
}
